package com.tensquare.article.service;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.tensquare.article.client.NoticeClient;
import com.tensquare.article.dao.ArticleDao;
import com.tensquare.article.pojo.Article;
import com.tensquare.article.pojo.Notice;
import com.tensquare.util.IdWorker;
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.DirectExchange;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.rabbit.core.RabbitAdmin;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Map;
import java.util.Set;

@Service
public class ArticleService {
    @Autowired
    private ArticleDao articleDao;
    @Autowired
    private NoticeClient noticeClient;
    @Autowired
    private IdWorker idWorker;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private RabbitTemplate rabbitTemplate;

    public List<Article> findAll() {
        return articleDao.selectList(null);
    }

    public Article findById(String articleId) {
        return articleDao.selectById(articleId);
    }

    public void save(Article article) {
        //TODO: 使用jwt鉴权获取当前用户的信息，用户id，也就是文章作者id
        String userId="3";
        article.setUserid(userId);
        //使用分布式id生成器
        String id=idWorker.nextId()+"";
        article.setId(id);

        //初始化数据
        article.setVisits(0);   //浏览数
        article.setThumbup(0);  //点赞数
        article.setComment(0);  //评论数

        //新增
        articleDao.insert(article);

        //新增文章后，创建消息，通知给订阅者
        //获取订阅者信息
        String authorKey="article_author_"+userId;
        Set<String> set = redisTemplate.boundSetOps(authorKey).members();
        for (String uid : set) {
            //创建消息对象
            Notice notice=new Notice();
            //接受消息用户的id
            notice.setReceiverId(uid);
            //进行操作用户的id
            notice.setOperatorId(userId);
            //操作类型
            notice.setAction("publish");
            //被操纵的对象
            notice.setTargetType("article");
            //被操作对象的id
            notice.setTargetId(id);
            //通知类型
            notice.setType("sys");

            noticeClient.save(notice);
        }
        //发消息给rabbitmq，就是新消息的通知
        //入库成功后，发送mq消息，内容是消息通知id
        rabbitTemplate.convertAndSend("article_subscribe", userId, id);
    }

    public void updateById(Article article) {
        //根据主键id修改
        articleDao.updateById(article);

        //根据条件修改
        //创建条件对象
        //EntityWrapper<Article> wrapper=new EntityWrapper<>();
        //wrapper.eq("id",article.getId());
        //设置条件
        //articleDao.update(article,wrapper);
    }

    public void deleteById(String articleId) {
        //根据主键id进行删除
        articleDao.deleteById(articleId);
    }

    public Page<Article> findByPage(Map<String, Object> map, Integer page, Integer size) {
        //设置查询条件
        EntityWrapper<Article> wrapper=new EntityWrapper<>();
        Set<String> keySet = map.keySet();
        for (String key : keySet) {
            //if (map.get(key)!=null){
            //    wrapper.eq(key,map.get(key));
            //}
            //第一个参数是否把后面的条件加入到查询条件中
            //和上面的if判断的写法是一样的效果，实现动态sql
            wrapper.eq(map.get(key)!=null,key,map.get(key));
        }
        //设置分页参数
        Page<Article> pageDate =new Page<>(page,size);
        //执行查询
        //第一个是分页参数，第二个是查询条件
        List<Article> list = articleDao.selectPage(pageDate, wrapper);
        pageDate.setRecords(list);

        //返回
        return pageDate;
    }

    public Boolean subscribe(String articleId, String userId) {
        //根据文章id查询文章作者id
        String authorId = articleDao.selectById(articleId).getUserid();

        //1.创建rabbitmq管理器
        RabbitAdmin rabbitAdmin=new RabbitAdmin(rabbitTemplate.getConnectionFactory());
        //2.声明交换机，发送新增文章消息
        DirectExchange exchange=new DirectExchange("article_subscribe");
        rabbitAdmin.declareExchange(exchange);
        //3.创建队列，每个用户都有自己的队列，通过用户id进行区分
        Queue queue=new Queue("article_subscribe_"+userId,true);
        //4.声明交换机和队列的绑定关系，需要确保队列只收到对应作者的新增文章消息
        Binding binding = BindingBuilder.bind(queue).to(exchange).with(authorId);
        //通过路由键进行绑定，队列只收到绑定作者的文章消息



        //存放用户的订阅信息的集合，存放作者id
        String userKey="article_subscribe_"+userId;
        //存放作者订阅者信息的集合，存放订阅者id
        String authorKey="article_author_"+authorId;
        //查询用户的订阅关系，是否有订阅该作者
        Boolean flag = redisTemplate.boundSetOps(userKey).isMember(authorId);
        //如果订阅作者，就取消订阅 返回false
        if (flag==true){
            //在用户订阅信息的集合中，删除订阅的作者
            redisTemplate.boundSetOps(userKey).remove(authorId);
            //作者订阅者信息中的集合中，删除订阅者
            redisTemplate.boundSetOps(authorKey).remove(userId);
            //如果取消订阅，删除队列绑定关系
            rabbitAdmin.removeBinding(binding);
            return false;
        }else {
            //如果没有订阅作者，就进行订阅返回true
            redisTemplate.boundSetOps(userKey).add(authorId);
            redisTemplate.boundSetOps(authorKey).add(userId);
            //如果订阅，则添加绑定关系
            rabbitAdmin.declareQueue(queue);
            rabbitAdmin.declareBinding(binding);
            return true;
        }
    }

    public void thumpup(String articleId,String userId){
        Article article=articleDao.selectById(articleId);
        article.setThumbup(article.getThumbup()+1);
        articleDao.updateById(article);

        //点赞成功后，需要发送消息给文章作者
        Notice notice=new Notice();
        //接收消息用户的id
        notice.setReceiverId(article.getUserid());
        //进行操作用户的id
        notice.setOperatorId(userId);
        //操作类型
        notice.setAction("publish");
        //被操作的对象
        notice.setTargetType("article");
        //被操作对象的id
        notice.setTargetId(articleId);
        //通知类型
        notice.setType("user");

        //保存消息
        noticeClient.save(notice);

        RabbitAdmin rabbitAdmin=new RabbitAdmin(rabbitTemplate.getConnectionFactory());
        //3.创建队列，每个用户都有自己的队列，通过作者id进行区分
        Queue queue=new Queue("article_thumbup_"+article.getUserid(),true);
        rabbitAdmin.declareQueue(queue);
        rabbitTemplate.convertAndSend("article_thumbup_",article.getUserid(),articleId);

    }

    //发消息给rabbitmq
}
